[Amazon Connect] 整形ログをKinesis Firehose経由で自動的に生成するようにしてみました
1 はじめに
AIソリューション部の平内(SIN)です。
Amazon Connect(以下、Connect)では、簡単にIVRに構築が可能ですが、実際に運用に入ると、PDCAなどを回すために、次のような要望が出てきます。
- IVRのみシステムで、どれ位、離脱があるのだろうか(受付完了までに到達せず諦めてしまうなど)
- 想定外の入力は、どのようなものがあるのだろうか(誘導のアナウンスは、適切なのか)
- アクセスの状況は?(申し込み電話をする時間帯は?、実際の予約の何日前?などに併せて、質問内容を最適化できないか?)
そして、前回、このような要求に応じるための一例としてログの整形を試してみました。
今回は、このような整形ログが自動的に出力されるようにしてみました。
2 エージェントイベント
Connectでは、エージェントの作業をリアルタイムで取得できるエージェントイベント(データストリーミング) があります。
このイベントをハンドルすると、接続完了時に、その時間や、コンタクトIDが入ったログを取得することができます。そこで、このストリームを、ハンドルして、自動的に整形ログを出力できるようにしてみました。
3 Kinesis Firehose
ストリーミングのログを処理するためには、Connectのインスタンス設定で、データストリーミングにKinesis Firehoseを設定します。(Kinesisストリームでも可能ですが、それほど、リアルタイムである必要もなさそうなので、簡単なFirehoseの方にしました。)
作成した、Kinesis Firehoseは、destinationをS3のバケットに設定しています。
Kinesis Firehoseは、バッファのサイスやタイムアウトの設定で、イベントをハンドルできるタイミングが少し遅れるので注意が必要です。エージェントイベントはデータ量が小さいので、バッファに貯まるのを待っていると、デバッグしにくいので、とりあえず、最小の 1MB or 60 secondsとしました。(運用に入ったら、大きくしても問題ないと思います。)
また、Transform source records with AWS LambdaをEnableとし、Lambdaファンクションを挟んでいます。このLambdaで、整形したログを生成する魂胆です。
4 Lambda
ストリームに挟んだLambdaのコードは、以下のとおりです。
このLambdaに入ってくるデータはFirehoseTransformationResultRecord[]のように複数のイベントがまとまって配列となっているので、それぞれを1レコード(1回の接続イベント)として処理しています。
イベントのメソッド(InitiationMethodがINBOUNDであるものを処理の対象とし、コンタクトID(ContactId)をフィルターパターンとしてとCloudWatchLogsに検索をかけます。
なお、CloudWatchLogsのストリーム名は、イベントの発生時間から組み立ててています。
ログ整形の実態(Contactクラス)は、前回使用したものと同じです。
ただ、今回は、出力を再びBase64でエンコードしてストリームに戻しました。こうすることで、S3への保存については、Kinesis Firehoseにおまかせできるので、簡単かなという判断です。
import { FirehoseTransformationEvent, FirehoseTransformationResultRecord } from "aws-lambda"; const instanceName = 'trial-instance'; const groupName = '/aws/connect/' + instanceName; const isDebug = true; exports.handle = async (event : FirehoseTransformationEvent) => { console.log(JSON.stringify(event)); let results:FirehoseTransformationResultRecord[] = []; for(var i=0; i < event.records.length; i++) { const record = event.records[i]; let expoertData = ''; const data = Buffer.from(record.data, 'base64').toString('utf8'); let agentEvent = JSON.parse(data) as AgentEvent; if (agentEvent.InitiationMethod == "INBOUND") { const filterPattern = agentEvent.ContactId.replace(/-/g,' '); // フィルタに記号が使用できない const dateStr = createDateStr(agentEvent.InitiationTimestamp); const events = await getEvents(groupName , dateStr, filterPattern); const contact = new Contact(events); expoertData += "ContactId = " + agentEvent.ContactId + '\n'; expoertData += 'Connect : ' + agentEvent.InitiationTimestamp + '\n'; expoertData += 'Disconnet : ' + agentEvent.DisconnectTimestamp + '\n'; expoertData += '\n'; expoertData += contact.print(isDebug); } results.push({ recordId: record.recordId, result: 'Ok', data: Buffer.from(expoertData, 'utf8').toString('base64') }); } return {records: results} };
全てのコードは下記におきました。詳細は、こちらをご確認下さい。
[GitHub] https://github.com/furuya02/izakaya-log/blob/master/src/connect/Transform.ts
5 S3
下記は、ストリームがS3へ出力されている様子です。
ダウンロードしてみると、整形されたログとなっている事が確認できます。
6 最後に
今回は、整形したログを自動的に出力する仕組みを考えてみました。
整形ログは、思ったより全体が見通せる、貴重な資料かも知れません。もしかすると、運用に関係なく、開発(デバッグ)中にも有効な仕組みかも知れません。
何かのヒントになれば幸いです。
※注:このようなログを平文で保存することの可否については、状況に応じて別途ご検討下さい。
弊社では、「Amazon Connect」の導入を検討している方を対象とした無料相談会を毎週開催中です。
また、音声を利用した各種ソリューションの導入支援を行っております。お気軽にお問い合わせください。